package funcparams

import (
	"fmt"
)

//省略号
func learnEllipsis(params ...int) {
	//可能传入不定个int进来
	fmt.Println("ellipsis的作用，可以传入不定个参数")
	for i, v := range params {
		fmt.Printf("index=%d, value=%d\n", i, v)
	}

}

//这个省略号，好像没有固定位置，可以跟在参数名后，也可以跟在类型前
func add(params ...int) (sum int) {
	for _, v := range params {
		sum += v
	}
	return
}

//go语言中，非常重要的特性，函数的一定公民特性 - 可以作为参数，返回值，可以赋值给另一个变量

type sub func(a, b int) int

func subImpl(a, b int) int {
	return a - b
}


func filter(f func(int) bool, values...int)[]int{
	res := make([]int, 0)
	for _, v := range values{
		if f(v){
			res = append(res, v)
		}
	}
	return res
}


func FuncParamsLearn() {
	learnEllipsis(9, 5, 6, 4, 5)

	sum := add(1, 2, 3, 4, 5)
	fmt.Println("计算1-5的和：", sum)

	//如果直接定义add的参数为slice,因为slice是引用传递，需要谨慎
	slice := []int{1, 2, 3, 4, 5}
	fmt.Println("计算1-5的和(打散slice)：", add(slice...))

	//省略号的用途
	//1.函数参数不定长
	//2，将slice打散
	//3.声明数组时，自动计算数组长度

	arr := [...]int{1, 2, 3}
	fmt.Printf("%T, len(arr)=%d\n", arr, len(arr))

	//函数的一等公民特性
	fmt.Println("1.将函数赋值给一个变量：")
	myFunc := add
	fmt.Printf("%T \n", myFunc)

	fmt.Println("2.在函数内部定义一个函数（匿名函数）：")
	myFunc2 := func(a, b int) int {
		return a + b
	}
	fmt.Printf("%T \n", myFunc2)

	res := func(a, b int) int {
		return a + b
	}(1, 9)
	fmt.Println("直接使用匿名函数计算：", res)


	var mySub sub = subImpl
	fmt.Printf("%T \n", mySub)

	var mySub2 sub = func (a, b int) int {
		return a -b
	}
	fmt.Println(mySub2(3, 1))

	fmt.Println("3.也可以把函数当做一个参数，传给另一个函数")
	//写一个函数用户过滤一部分数据
	scores := []int{50,60,85,78,94,45,88}
	newScores := filter(func (v int) bool{
		if v >=60{
			return true
		} else {
			return false
		}
	}, scores...)
	fmt.Println(newScores)
}
